#include "stdafx.h"

#include "gp_Ax3.h"
#include "gp_Ax1.h"
#include "gp_Pnt.h"
#include "gp_Ax2.h"
#include "gp_Trsf.h"
#include "gp_Vec.h"
#include "gp_Torus.h"
#include "gp.h"
#include "TColStd_Array1OfReal.h"

void gp_Torus::Coefficients (TColStd_Array1OfReal& Coef) const
{
	// Dans le repere local du tore :
	// X*X + Y*Y + Z*Z - 2.0 * majorRadius * sqrt (X*X + Y*Y)
	// - minorRadius * minorRadius + majorRadius * majorRadius = 0.0
	// X**4 + Y **4 + 2.0 * (X*Y)**2 + 2.0 * (X*Z)**2 + 2.0 * (Y*Z)**2 -
	// 2.0 * (majorRadius + minorRadius) * (X**2 + Y**2) +
	// 2.0 * (majorRadius - minorRadius) * Z**2 - 2.0 *
	// majorRadius * minorRadius = 0.0
	int Low = Coef.Lower();
	Standard_DimensionError_Raise_if (Coef.Length() < 31, " ");
	gp_Trsf T;
	double SumRadius = (majorRadius * majorRadius +
		minorRadius * minorRadius);
	double SubRadius = (majorRadius * majorRadius -
		minorRadius * minorRadius);
	T.SetTransformation (pos);
	double T11 = T.Value (1, 1);
	double T12 = T.Value (1, 2);
	double T13 = T.Value (1, 3);
	double T14 = T.Value (1, 4);
	double T21 = T.Value (2, 1);
	double T22 = T.Value (2, 2);
	double T23 = T.Value (2, 3);
	double T24 = T.Value (2, 4);
	double T31 = T.Value (3, 1);
	double T32 = T.Value (3, 2);
	double T33 = T.Value (3, 3);
	double T34 = T.Value (3, 4);
	Coef(Low) = RealPow (T11, 4) + RealPow (T21, 4) + RealPow(T31, 4) +
		2.0 * (T11 * T11 * T21 * T21 + T11 * T11 * T31 * T31 +
		T21 * T21 * T31 * T31);
	Coef(Low+1) = RealPow (T12, 4) + RealPow (T22, 4) + RealPow(T32, 4) +
		2.0 * (T12 * T12 * T22 * T22 + T12 * T12 * T32 * T32 +
		T22 * T22 * T32 * T32);
	Coef(Low+2) = RealPow (T13, 4) + RealPow (T23, 4) + RealPow(T33, 4) +
		2.0 * (T13 * T13 * T23 * T23 + T13 * T13 * T33 * T33 +
		T23 * T23 * T33 * T33);
	Coef(Low+3) = 4.0 * (RealPow (T11, 3) * T12 + RealPow (T21, 3) * T22 +
		RealPow (T31, 3) * T32 + T11 * T11 * T21 * T22 +  T21 * T21 * T11 * T12 +
		T11 * T11 * T31 * T32 + T31 * T31 * T11 * T12 + T21 * T21 * T31 * T32
		+ T31 * T31 * T21 * T22);
	Coef(Low+4) = 4.0 * (RealPow (T11, 3) * T13 + RealPow (T21, 3) * T23 +
		RealPow (T31, 3) * T33 + T11 * T11 * T21 * T23 + T21 * T21 * T11 * T13 +
		T11 * T11 * T31 * T33 + T31 * T31 * T11 * T13 + T21 * T21 * T31 * T33
		+ T31 * T31 * T21 * T23);
	Coef(Low+5) = 4.0 * (RealPow (T12, 3) * T11 + RealPow (T22, 3) * T21 +
		RealPow (T32, 3) * T31  + T12 * T12 * T21 * T22 + T22 * T22 * T11 * T12 +
		T12 * T12 * T31 * T32 + T32 * T32 * T11 * T12 + T22 * T22 * T31 * T32
		+ T32 * T32 * T21 * T22);
	Coef(Low+6) = 4.0 * (RealPow (T12, 3) * T13 + RealPow (T22, 3) * T23 +
		RealPow (T32, 3) * T33 + T12 * T12 * T22 * T23 + T22 * T22 * T12 * T13 +
		T12 * T12 * T32 * T33 + T32 * T32 * T12 * T13 + T22 * T22 * T32 * T33
		+ T32 * T32 * T22 * T23);
	Coef(Low+7) = 4.0 * (RealPow (T13, 3) * T11 + RealPow (T23, 3) * T21 +
		RealPow (T33, 3) * T31 + T13 * T13 * T21 * T23 + T23 * T23 * T11 * T13 +
		T13 * T13 * T31 * T33 + T33 * T33 * T11 * T13 + T23 * T23 * T31 * T33
		+ T33 * T33 * T21 * T23);
	Coef(Low+8) = 4.0 * (RealPow (T13, 3) * T12 + RealPow (T23, 3) * T22 +
		RealPow (T33, 3) * T32 + T13 * T13 * T22 * T23 + T23 * T23 * T12 * T13 +
		T13 * T13 * T32 * T33 + T33 * T33 * T12 * T13 + T23 * T23 * T32 * T33
		+ T33 * T33 * T22 * T23);
	Coef(Low+9) = 6.0 * (T11 * T11 * T12 * T12 + T21 * T21 * T22 * T22 +
		T31 * T31 * T32 * T32) + 8.0 * ( T11 * T12 * T21 * T22 +
		T11 * T12 * T31 * T32 + T21 * T22 * T31 * T32) +
		2.0 * (T11 * T11 * T22 * T22 + T11 * T11 * T32 * T32 +
		T21 * T21 * T32 * T32 + T12 * T12 * T21 * T21 +
		T12 * T12 * T31 * T31 + T22 * T22 * T31 * T31 );
	Coef(Low+10) = 6.0 * (T11 * T11 * T13 * T13 + T21 * T21 * T23 * T23 +
		T31 * T31 * T33 * T33) + 8.0 * ( T11 * T13 * T21 * T23 +
		T11 * T13 * T31 * T33 + T21 * T23 * T31 * T33) +
		2.0 * (T11 * T11 * T23 * T23 + T11 * T11 * T33 * T33 +
		T21 * T21 * T33 * T33 + T13 * T13 * T21 * T21 +
		T13 * T13 * T31 * T31 + T23 * T23 * T31 * T31);
	Coef(Low+11) = 6.0 * (T12 * T12 * T13 * T13 + T22 * T22 * T23 * T23 +
		T32 * T32 * T33 * T33) + 8.0 * ( T12 * T13 * T22 * T23 +
		T12 * T23 * T32 * T33 + T22 * T23 * T32 * T33) + 
		2.0 * (T12 * T12 * T23 * T23 + T12 * T12 * T33 * T33 +
		T22 * T22 * T33 * T33 +  T13 * T13 * T22 * T22 +
		T13 * T13 * T32 * T32 + T23 * T23 * T32 * T32);
	Coef(Low+12) = 4.0 * (RealPow (T11, 3) * T14 + RealPow (T21, 3) * T24 +
		RealPow (T31, 3) * T34 + T11 * T11 * T21 * T24 + T11 * T11 * T31 * T34 +
		T21 * T21 * T31 * T34 + T21 * T21 * T11 * T14 +
		T31 * T31 * T11 * T34 + T31 * T31 * T21 * T24);
	Coef(Low+13) = 4.0 * (RealPow (T12, 3) * T14 + RealPow (T22, 3) * T24 +
		RealPow (T32, 3) * T34 + T12 * T12 * T22 * T24 + T12 * T12 * T32 * T34 +
		T22 * T22 * T32 * T34 + T22 * T22 * T12 * T14 +
		T32 * T32 * T12 * T34 + T32 * T32 * T22 * T24);
	Coef(Low+14) = 4.0 * (RealPow (T13, 3) * T14 + RealPow (T23, 3) * T24 +
		RealPow (T33, 3) * T34 + T13 * T13 * T23 * T24 + T13 * T13 * T33 * T34 +
		T23 * T23 * T33 * T34 + T23 * T23 * T13 * T14 +
		T33 * T33 * T13 * T34 + T33 * T33 * T23 * T24);
	Coef(Low+15) = 4.0 * (T11 * T11 * T22 * T24 + T11 * T11 * T32 * T34 +
		T21 * T21 * T32 * T34 + T21 * T21 * T12 * T14 + T31 * T31 * T12 * T14
		+ T31 * T31 * T22 * T24);
	Coef(Low+16) = 4.0 * (T11 * T11 * T23 * T24 + T11 * T11 * T33 * T34 +
		T21 * T21 * T33 * T34 + T21 * T21 * T13 * T14 + T31 * T31 * T13 * T14
		+ T31 * T31 * T23 * T24);
	Coef(Low+17) = 4.0 * (T12 * T12 * T21 * T24 + T12 * T12 * T31 * T34 +
		T22 * T22 * T31 * T34 + T22 * T22 * T11 * T14 + T32 * T32 * T11 * T14
		+ T32 * T32 * T21 * T24);
	Coef(Low+18) = 4.0 * (T12 * T12 * T23 * T24 + T12 * T12 * T33 * T34 +
		T22 * T22 * T33 * T34 + T22 * T22 * T13 * T14 + T32 * T32 * T13 * T14
		+ T32 * T32 * T23 * T24);
	Coef(Low+19) = 4.0 * (T13 * T13 * T21 * T24 + T13 * T13 * T31 * T34 +
		T23 * T23 * T31 * T34 + T23 * T23 * T11 * T14 + T33 * T33 * T11 * T14
		+ T33 * T33 * T21 * T24);
	Coef(Low+20) = 4.0 * (T13 * T13 * T22 * T24 + T13 * T13 * T32 * T34 +
		T23 * T23 * T32 * T34 + T23 * T23 * T12 * T14 + T33 * T33 * T12 * T14
		+ T33 * T33 * T22 * T24);
	Coef(Low+21) = 6.0 * (T11 * T11 * T14 * T14 + T21 * T21 * T24 * T24 +
		T31 * T31 * T34 * T34) + 2.0 * (T11 * T11 * T24 * T24 +
		T11 * T11 * T34 * T34 + T21 * T21 * T34 * T34 + T21 * T21 * T14 * T14
		+ T31 * T31 * T14 * T14 + T31 * T31 * T24 * T24 - 
		SumRadius * (T11 * T11 + T21 * T21) + SubRadius * T31 * T31);
	Coef(Low+22) = 6.0 * (T12 * T12 * T14 * T14 + T22 * T22 * T24 * T24 +
		T32 * T32 * T34 * T34) + 2.0 * (T12 * T12 * T24 * T24 +
		T12 * T12 * T34 * T34 + T22 * T22 * T34 * T34 + T22 * T22 * T14 * T14
		+ T32 * T32 * T14 * T14 + T32 * T32 * T24 * T24 - 
		SumRadius * (T12 * T12 + T22 * T22) + SubRadius * T32 * T32);
	Coef(Low+23) = 6.0 * (T13 * T13 * T14 * T14 + T23 * T23 * T24 * T24 +
		T33 * T33 * T34 * T34) + 2.0 * (T13 * T13 * T24 * T24 +
		T13 * T13 * T34 * T34 + T23 * T23 * T34 * T34 + T23 * T23 * T14 * T14
		+ T33 * T33 * T14 * T14 + T33 * T33 * T24 * T24 - 
		SumRadius * (T13 * T13 + T23 * T23) + SubRadius * T33 * T33);
	Coef(Low+24) = 8.0 * (T11 * T14 * T22 * T24 + T11 * T14 * T32 * T34 +
		T21 * T24 * T32 * T34 + T21 * T24 * T12 * T14 + T31 * T34 * T12 * T14
		+ T31 * T34 *T22 * T24) + 4.0 * (T11 * T12 * T24 * T24  +
		T11 * T12 * T34 * T34 + T21 * T22 * T34 * T34 + T21 * T22 * T14 * T14
		+ T31 * T32 * T14 * T14 + T31 * T32 * T24 * T24 - SumRadius * (
		T11 * T12 + T21 * T22) + SubRadius * T31 * T32);
	Coef(Low+25) = 8.0 * (T11 * T14 * T23 * T24 + T11 * T14 * T33 * T34 +
		T21 * T24 * T33 * T34 + T21 * T24 * T13 * T14 + T31 * T34 * T13 * T14
		+ T31 * T34 *T23 * T24) + 4.0 * (T11 * T13 * T24 * T24  +
		T11 * T13 * T34 * T34 + T21 * T23 * T34 * T34 + T21 * T23 * T14 * T14
		+ T31 * T33 * T14 * T14 + T31 * T33 * T24 * T24 - SumRadius * (
		T11 * T13 + T21 * T22) + SubRadius * T31 * T33);
	Coef(Low+26) = 8.0 * (T12 * T14 * T23 * T24 + T12 * T14 * T33 * T34 +
		T22 * T24 * T33 * T34 + T22 * T24 * T13 * T14 + T32 * T34 * T13 * T14
		+ T32 * T34 *T23 * T24) + 4.0 * (T12 * T13 * T24 * T24  +
		T12 * T13 * T34 * T34 + T22 * T23 * T34 * T34 + T22 * T23 * T14 * T14
		+ T32 * T33 * T14 * T14 + T32 * T33 * T24 * T24 - SumRadius * (
		T12 * T13 + T21 * T22) + SubRadius * T32 * T33);


	Coef(Low+27) = 4.0 * (RealPow (T14, 3) * T11 + RealPow (T24, 3) * T21 +
		RealPow (T34, 3) * T31  +  T11 * T14 * T24 * T24 + T11 * T14 * T34 * T34
		+ T21 * T24 * T34 * T34 + T21 * T24 * T14 * T14 +
		T31 * T34 * T14 * T14 + T31 * T34 * T24 * T24 + SubRadius * T31 * T34
		- SumRadius * (T11 * T14 + T21 * T24));
	Coef(Low+28) = 4.0 * (RealPow (T14, 3) * T12 + RealPow (T24, 3) * T22 +
		RealPow (T34, 3) * T32  +  T12 * T14 * T24 * T24 + T12 * T14 * T34 * T34
		+ T22 * T24 * T34 * T34 + T22 * T24 * T14 * T14 +
		T32 * T34 * T14 * T14 + T32 * T34 * T24 * T24 + SubRadius * T32 * T34
		- SumRadius * (T12 * T14 + T22 * T24));
	Coef(Low+29) = 4.0 * (RealPow (T14, 3) * T13 + RealPow (T24, 3) * T23 +
		RealPow (T34, 3) * T33  +  T13 * T14 * T24 * T24 + T13 * T14 * T34 * T34
		+ T23 * T24 * T34 * T34 + T23 * T24 * T14 * T14 +
		T33 * T34 * T14 * T14 + T33 * T34 * T24 * T24 + SubRadius * T33 * T34
		- SumRadius * (T13 * T14 + T21 * T24));
	Coef(Low+30) = RealPow (T14, 4) + RealPow (T24, 4) + RealPow (T34, 4) + 2.0 * (
		T14 * T14 * T24 * T24 + T14 * T14 * T34 * T34 + T24 * T24 * T34 * T34
		- SumRadius * (T14 * T14 + T24 * T24) + SubRadius * T34 * T34 -
		majorRadius * majorRadius * minorRadius * minorRadius);
}

void gp_Torus::Mirror (const gp_Pnt& P)
{ pos.Mirror (P); }

gp_Torus gp_Torus::Mirrored (const gp_Pnt& P) const
{
	gp_Torus C = *this;
	C.pos.Mirror (P);
	return C;
}

void gp_Torus::Mirror (const gp_Ax1& A1)
{ pos.Mirror (A1); }

gp_Torus gp_Torus::Mirrored (const gp_Ax1& A1) const
{
	gp_Torus C = *this;
	C.pos.Mirror (A1);
	return C;
}

void gp_Torus::Mirror (const gp_Ax2& A2)
{ pos.Mirror (A2); }

gp_Torus gp_Torus::Mirrored (const gp_Ax2& A2) const
{
	gp_Torus C = *this;
	C.pos.Mirror (A2);
	return C;
}

 gp_Torus::gp_Torus () :
majorRadius (DBL_MAX),
minorRadius (DBL_MIN)
{ }

 gp_Torus::gp_Torus (const gp_Ax3& A3,
			   const double MajorRadius,
			   const double MinorRadius) :
			   pos(A3),
			   majorRadius (MajorRadius),
			   minorRadius (MinorRadius)
{
  Standard_ConstructionError_Raise_if
    (MinorRadius < 0.0 || MajorRadius < 0.0,"");
}

 void gp_Torus::SetAxis (const gp_Ax1& A1)
{ pos.SetAxis (A1); }

 void gp_Torus::SetLocation (const gp_Pnt& Loc)
{ pos.SetLocation (Loc); }

 void gp_Torus::SetMajorRadius (const double MajorRadius)
{
  Standard_ConstructionError_Raise_if
    (MajorRadius - minorRadius <= gp::Resolution(),"");
  majorRadius = MajorRadius;
}

 void gp_Torus::SetMinorRadius (const double MinorRadius)
{
  Standard_ConstructionError_Raise_if
    (MinorRadius < 0.0 || majorRadius - MinorRadius <= gp::Resolution(),"");
  minorRadius = MinorRadius;
}

 void gp_Torus::SetPosition (const gp_Ax3& A3)
{ pos = A3; }

 double gp_Torus::Area () const
{ return 4.0 * M_PI * M_PI * minorRadius * majorRadius; }

 void gp_Torus::UReverse()
{ pos.YReverse(); }

 void gp_Torus::VReverse()
{ pos.ZReverse(); }

 bool gp_Torus::Direct() const
{ return pos.Direct(); }

 const gp_Ax1& gp_Torus::Axis () const
{ return pos.Axis(); }

 const gp_Pnt& gp_Torus::Location () const
{ return pos.Location(); }

 const gp_Ax3& gp_Torus::Position () const
{ return pos; }

 double gp_Torus::MajorRadius () const
{ return majorRadius; }

 double gp_Torus::MinorRadius () const
{ return minorRadius; }

 double gp_Torus::Volume () const
{ return (M_PI * minorRadius * minorRadius) * (2.0 * M_PI * majorRadius); }

 gp_Ax1 gp_Torus::XAxis () const
{ return gp_Ax1(pos.Location(), pos.XDirection()); }

 gp_Ax1 gp_Torus::YAxis () const
{ return gp_Ax1(pos.Location(), pos.YDirection()); }

 void gp_Torus::Rotate (const gp_Ax1& A1,
			      const double Ang)
{ pos.Rotate (A1, Ang); }

 gp_Torus gp_Torus::Rotated (const gp_Ax1& A1,
				   const double Ang) const
{
  gp_Torus C = *this;
  C.pos.Rotate (A1, Ang);
  return C;
}

 void gp_Torus::Scale (const gp_Pnt& P,
			     const double S)
{
  pos.Scale (P, S);      
  double s = S;
  if (s < 0) s = - s;
  majorRadius *= s;
  minorRadius *= s;
}

 gp_Torus gp_Torus::Scaled (const gp_Pnt& P,
				  const double S) const
{
  gp_Torus C = *this;
  C.pos.Scale (P, S);
  C.majorRadius *= S;
  if (C.majorRadius < 0) C.majorRadius = - C.majorRadius;
  C.minorRadius *= S;
  if (C.minorRadius < 0) C.minorRadius = - C.minorRadius;
  return C;
}

 void gp_Torus::Transform (const gp_Trsf& T)
{
  pos.Transform (T);
  double t = T.ScaleFactor();
  if(t < 0 ) t = - t;
  minorRadius *= t;
  majorRadius *= t;
}

 gp_Torus gp_Torus::Transformed (const gp_Trsf& T) const
{
  gp_Torus C = *this;
  C.pos.Transform (T);
  C.majorRadius *= T.ScaleFactor();
  if (C.majorRadius < 0) C.majorRadius = - C.majorRadius;
  C.minorRadius *= T.ScaleFactor();
  if (C.minorRadius < 0) C.minorRadius = - C.minorRadius;
  return C;
}

 void gp_Torus::Translate (const gp_Vec& V)
{ pos.Translate (V); }

 gp_Torus gp_Torus::Translated (const gp_Vec& V) const
{
  gp_Torus C = *this;
  C.pos.Translate (V);
  return C;
}

 void gp_Torus::Translate (const gp_Pnt& P1,
				 const gp_Pnt& P2)
{ pos.Translate (P1, P2); }

 gp_Torus gp_Torus::Translated (const gp_Pnt& P1,
				      const gp_Pnt& P2) const
{
  gp_Torus C = *this;
  C.pos.Translate (P1, P2);
  return C;
}

